namespace Resharper.Abstractions.CodeDom.Expressions.BinaryExpressions
{
  using System.Diagnostics;
  using JetBrains.Annotations;
  using JetBrains.ReSharper.Psi.CSharp.Tree;
  using Resharper.Abstractions.CodeDom.Expressions.LiteralExpressions;

  /// <summary>Defines the <see cref="LiteralExpression"/> class.</summary>
  public class BinaryExpression : Expression
  {
    #region Constructors and Destructors

    /// <summary>Initializes a new instance of the <see cref="LiteralExpression"/> class.</summary>
    /// <param name="binaryExpression">The expression.</param>
    internal BinaryExpression([NotNull] IBinaryExpression binaryExpression) : base(binaryExpression)
    {
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets the left operand.
    /// </summary>
    [CanBeNull]
    public Expression LeftOperand
    {
      get
      {
        var expression = this.InternalBinaryExpression.LeftOperand;
        if (expression == null)
        {
          return null;
        }

        return ExpressionFactory.GetExpression(expression);
      }
      set
      {
        Debug.Assert(value != null, "value != null");

        this.InternalBinaryExpression.SetLeftOperand((ICSharpExpression)value.InternalExpression);
      }
    }

    /// <summary>
    /// Gets the right operand.
    /// </summary>
    [CanBeNull]
    public Expression RightOperand
    {
      get
      {
        var expression = this.InternalBinaryExpression.RightOperand;
        if (expression == null)
        {
          return null;
        }

        return ExpressionFactory.GetExpression(expression);
      }
      set
      {
        Debug.Assert(value != null, "value != null");

        this.InternalBinaryExpression.SetRightOperand((ICSharpExpression)value.InternalExpression);
      }
    }

    /// <summary>
    /// Gets the operator sign.
    /// </summary>
    [NotNull]
    public string OperatorSign
    {
      get
      {
        var token = this.InternalBinaryExpression.OperatorSign;

        return token != null ? token.GetText() : string.Empty;
      }
    }

    /// <summary>
    /// Gets the operator sign text range.
    /// </summary>
    public bool OperatorSignContains(int offset)
    {
      var operatorSign = this.InternalBinaryExpression.OperatorSign;
      if (operatorSign == null)
      {
        return false;
      }

      var range = operatorSign.GetNavigationRange();

      return range.TextRange.Contains(offset);
    }

    /// <summary>The literal expression field.</summary>
    [NotNull]
    internal IBinaryExpression InternalBinaryExpression
    {
      get
      {
        return (IBinaryExpression)this.InternalExpression;
      }
    }

    #endregion
  }
}